/**
 @file sys_usw_interrupt.h

 @date 2012-10-23

 @version v2.0

*/
#ifndef _SYS_USW_INTERRUPT_H
#define _SYS_USW_INTERRUPT_H
#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "ctc_debug.h"
#include "ctc_const.h"
#include "ctc_interrupt.h"
#include "drv_api.h"

/***************************************************************
 *
 *  Defines and Macros
 *
 ***************************************************************/
#define SYS_USW_MAX_SYS_INTR_TYPE  16 /*ctc intr type map to many sys intr type*/

#define SYS_USW_INTR_ABNORMAL_LOG_PROCESS(lchip, intr_v,i,j,low_bmp) \
do{\
    uint32 loop;\
    sys_intr_abnormal_log_t log_intr;\
    log_intr.intr = intr_v;\
    log_intr.sub_intr = i;\
    log_intr.low_intr = j;\
    log_intr.real_intr = 0;\
    if(low_bmp[0] || low_bmp[1] || low_bmp[2] || low_bmp[3])\
    {\
        for(loop=0; loop < 32*CTC_INTR_STAT_SIZE; loop++)\
        {\
            if(low_bmp[loop/32] == 0)\
            {\
                loop = (loop/32 + 1) * CTC_UINT32_BITS-1;\
                continue;\
            }\
            if(CTC_BMP_ISSET(low_bmp, loop))\
            {\
                log_intr.real_intr = loop;\
                _sys_usw_intr_log_normal_intr(lchip, log_intr);\
            }\
        }\
    }\
    else\
    {\
        _sys_usw_intr_log_normal_intr(lchip, log_intr);\
    }\
}while(0)

/**
 @brief [GG] SYS_INTR_GB_DMA_FUNC interrupt sub-type
*/
enum sys_interrupt_type_sub_dma_func_e
{
    SYS_INTR_SUB_DMA_FUNC_CHAN_0 = 0,
    SYS_INTR_SUB_DMA_FUNC_CHAN_1,
    SYS_INTR_SUB_DMA_FUNC_CHAN_2,
    SYS_INTR_SUB_DMA_FUNC_CHAN_3,
    SYS_INTR_SUB_DMA_FUNC_CHAN_4,
    SYS_INTR_SUB_DMA_FUNC_CHAN_5,
    SYS_INTR_SUB_DMA_FUNC_CHAN_6,
    SYS_INTR_SUB_DMA_FUNC_CHAN_7,
    SYS_INTR_SUB_DMA_FUNC_CHAN_8,
    SYS_INTR_SUB_DMA_FUNC_CHAN_9,
    SYS_INTR_SUB_DMA_FUNC_CHAN_10,
    SYS_INTR_SUB_DMA_FUNC_CHAN_11,
    SYS_INTR_SUB_DMA_FUNC_CHAN_12,
    SYS_INTR_SUB_DMA_FUNC_CHAN_13,
    SYS_INTR_SUB_DMA_FUNC_CHAN_14,
    SYS_INTR_SUB_DMA_FUNC_CHAN_15,
    SYS_INTR_SUB_DMA_FUNC_MAX
};
typedef enum sys_interrupt_type_sub_dma_func_e  sys_interrupt_type_sub_dma_func_t;

enum sys_interrupt_type_sub_pcie_e
{
    SYS_INTR_SUB_PCIE_INTF_REG_BURST_DONE = 0,

    SYS_INTR_SUB_PCIE_INTF_MAX
};
typedef enum sys_interrupt_type_sub_pcie_e sys_interrupt_type_sub_pcie_t;

enum sys_interrupt_type_e
{
    SYS_INTR_CHIP_FATAL = 0,
    SYS_INTR_CHIP_NORMAL = 1,

    SYS_INTR_FUNC_PTP_TS_CAPTURE_FIFO = 2,
    SYS_INTR_FUNC_PTP_TOD_PULSE_IN = 3,
    SYS_INTR_FUNC_PTP_TOD_CODE_IN_RDY = 4,
    SYS_INTR_FUNC_PTP_SYNC_PULSE_IN = 5,
    SYS_INTR_FUNC_PTP_SYNC_CODE_IN_RDY = 6,
    SYS_INTR_FUNC_PTP_SYNC_CODE_IN_ACC = 7,

    SYS_INTR_FUNC_STATS_STATUS_ADDR = 8,
    SYS_INTR_FUNC_MET_LINK_SCAN_DONE = 9,

    SYS_INTR_FUNC_MDIO_CHANGE_0 = 10,/* only duet2 */
    SYS_INTR_FUNC_MDIO_CHANGE_1 = 11,/* only duet2 */


    SYS_INTR_FUNC_CHAN_LINKDOWN_SCAN = 12,
    SYS_INTR_FUNC_IPFIX_USEAGE_OVERFLOW = 13,
    SYS_INTR_FUNC_FIB_ACC_LEARN_OUT_FIFO = 14,

    SYS_INTR_FUNC_OAM_DEFECT_CACHE = 15,
    SYS_INTR_FUNC_BSR_C2C_PKT_CONGESTION = 16,
    SYS_INTR_FUNC_BSR_TOTAL_CONGESTION = 17,

    SYS_INTR_FUNC_BSR_OAM_CONGESTION = 18,
    SYS_INTR_FUNC_BSR_DMA_CONGESTION = 19,

    SYS_INTR_FUNC_BSR_CRITICAL_PKT_CONGESTION = 20,
    SYS_INTR_FUNC_OAM_AUTO_GEN = 21,

    SYS_INTR_PCS_LINK_31_0 = 22,
    SYS_INTR_PCS_LINK_47_32 = 23,

    SYS_INTR_FUNC_MDIO_XG_CHANGE_0 = 24,
    SYS_INTR_FUNC_MDIO_XG_CHANGE_1 = 25,

    SYS_INTR_PCIE_BURST_DONE = 26,
    SYS_INTR_DMA = 27,

    SYS_INTR_MCU_SUP = 28,/* only duet2 */
    SYS_INTR_MCU_NET = 29,/* only duet2 */

    /* TsingMa new added */
    SYS_INTR_FUNC_STMCTL_STATE = 30,  /* tsingma and tsingma.mx */
    SYS_INTR_FUNC_EPE_IPFIX_USEAGE_OVERFLOW = 31, /* tsingma */
    SYS_INTR_GPIO = 32, /* tsingma */
    SYS_INTR_SOC_SYS = 33,/* tsingma */

    /* TsingMa.MX new added */
    SYS_INTR_FUNC_TCAM_SCAN_ERROR = 34,
    SYS_INTR_FUNC_SVC_POLICING_STATUS_ADDR = 35,
    SYS_INTR_FUNC_DP1_MDIO_XG_CHANGE_0 = 36,
    SYS_INTR_FUNC_DP1_MDIO_XG_CHANGE_1 = 37,
    SYS_INTR_FUNC_SPN_DMA_DROPL = 38,
    SYS_INTR_FUNC_SPN_DMA_DROPM = 39,
    SYS_INTR_FUNC_SPN_CPU_REPORTL = 40,
    SYS_INTR_FUNC_SPN_CPU_REPORTM = 41,
    SYS_INTR_FUNC_CPU_MAC = 42,
    SYS_INTR_FUNC_DP1_BSR_C2C_PKT_CONGESTION = 43,
    SYS_INTR_FUNC_DP1_BSR_TOTAL_CONGESTION = 44,
    SYS_INTR_FUNC_DP1_BSR_OAM_CONGESTION = 45,
    SYS_INTR_FUNC_DP1_BSR_DMA_CONGESTION = 46,
    SYS_INTR_FUNC_DP1_BSR_CRITICAL_PKT_CONGESTION = 47,
    SYS_INTR_FUNC_FLEX_DP0 = 48,
    SYS_INTR_FUNC_FLEX_DP1 = 49,
    SYS_INTR_FUNC_OMC_TR = 50,
    SYS_INTR_FUNC_OMC_TL = 51,
    SYS_INTR_FUNC_OMC_BR = 52,
    SYS_INTR_FUNC_OMC_BL = 53,
    SYS_INTR_FUNC_DP0_MACSEC_RX = 54,
    SYS_INTR_FUNC_DP1_MACSEC_RX = 55,
    SYS_INTR_FUNC_DP0_MACSEC_TX = 56,
    SYS_INTR_FUNC_DP1_MACSEC_TX = 57,
    SYS_INTR_FUNC_DP0_MC_MAC0 = 58,
    SYS_INTR_FUNC_DP0_MC_MAC1 = 59,
    SYS_INTR_FUNC_DP0_MC_MAC2 = 60,
    SYS_INTR_FUNC_DP0_MC_MAC3 = 61,
    SYS_INTR_FUNC_DP1_MC_MAC0 = 62,
    SYS_INTR_FUNC_DP1_MC_MAC1 = 63,
    SYS_INTR_FUNC_DP1_MC_MAC2 = 64,
    SYS_INTR_FUNC_DP1_MC_MAC3 = 65,
    SYS_INTR_FUNC_PTP_TOD_PULSE = 66,
    SYS_INTR_FUNC_PTP_SYNC_PULSE = 67,
    SYS_INTR_FUNC_FLEXE0_MCU_REQ = 68,
    SYS_INTR_FUNC_FLEXE1_MCU_REQ = 69,
    SYS_INTR_FUNC_MISC_MCU_REQ = 70,
    SYS_INTR_FUNC_ECPU = 71,
    SYS_INTR_FUNC_SCPU = 72,

    /* Arctic New Add */
    SYS_INTR_FUNC_MAC = 73,
    SYS_INTR_FUNC_BSR_ERM_MON = 74,
    SYS_INTR_FUNC_BSR_IRM_MON = 75,
    SYS_INTR_FUNC_BSR_CONGESTION = 76,
    SYS_INTR_FUNC_OAM_TWAMP = 77,
    SYS_INTR_FUNC_MISC_EVENT = 78,
    SYS_INTR_FUNC_MACSEC = 79,
    SYS_INTR_FUNC_STATS_STATUS_ADDR_SLICE_1 = 80,
    SYS_INTR_FUNC_STATS_STATUS_ADDR_SLICE_2 = 81,
    SYS_INTR_FUNC_STATS_STATUS_ADDR_SLICE_3 = 82,
    SYS_INTR_FUNC_STMCTL_STATE_1 = 83,
    SYS_INTR_FUNC_STMCTL_STATE_2 = 84,
    SYS_INTR_FUNC_STMCTL_STATE_3 = 85,
    SYS_INTR_FUNC_SVC_POLICING_STATUS_ADDR_1 = 86,
    SYS_INTR_FUNC_SVC_POLICING_STATUS_ADDR_2 = 87,
    SYS_INTR_FUNC_SVC_POLICING_STATUS_ADDR_3 = 88,
    SYS_INTR_CPU_SUB_DECODE_0 = 89,
    SYS_INTR_CPU_SUB_DECODE_1 = 90,
    SYS_INTR_CPU_SUB_DECODE_2 = 91,
    SYS_INTR_CPU_SUB_DECODE_3 = 92,
    SYS_INTR_CPU_SUB_ECPU_00 = 93,
    SYS_INTR_CPU_SUB_ECPU_01 = 94,
    SYS_INTR_CPU_SUB_ECPU_10 = 95,
    SYS_INTR_CPU_SUB_ECPU_11 = 96,
    SYS_INTR_CPU_SUB_UART = 97,
    SYS_INTR_CPU_SUB_QSPI = 98,
    SYS_INTR_CPU_SUB_GPIO = 99,
    SYS_INTR_FUNC_PTP_SYNC_PULSE1 = 100,
    SYS_INTR_FUNC_PTP_SYNC_CODE_IN_RDY1 = 101,
    SYS_INTR_FUNC_PTP_TX_TS_FIFO_0_START = 102,
    SYS_INTR_FUNC_PTP_TX_TS_FIFO_0_END = 121,
    SYS_INTR_FUNC_PTP_TX_TS_FIFO_1_START = 122,
    SYS_INTR_FUNC_PTP_TX_TS_FIFO_1_END = 141,

    /* TsingmaGx New Add */
    SYS_INTR_FUNC_DP0_MC_MAC4 = 142,
    SYS_INTR_FUNC_DP1_MC_MAC4 = 143,

    SYS_INTR_MAX
};
typedef enum sys_interrupt_type_e sys_interrupt_type_t;

#define SYS_AT_INTR_MAX_CORE_NUM 2
enum sys_interrupt_flexe_sub_type_e
{
    SYS_INTR_FLEXE_SUB_TYPE_OH,
    SYS_INTR_FLEXE_SUB_TYPE_PTP,
    SYS_INTR_FLEXE_SUB_TYPE_MAX
};
typedef enum sys_interrupt_flexe_sub_type_e sys_interrupt_flexe_sub_type_t;

/**
 @brief [GG] Define struct for sys inter type
*/
struct sys_intr_type_s
{
    uint32  intr;                   /**<[GG] sup-level interrupt type defined in ctc_interrupt_type_CHIP_t */
    uint32  sub_intr;            /**<[GG] sub-level interrupt type defined in ctc_interrupt_type_CHIP_sub_SUP_t */
    uint32  low_intr;            /**<[GG] low-level interrupt type, used only for fatal and normal interrupt  */
    uint32  lvl4_intr;            /**<[AT] level 4 interrupt type, used only for fatal and normal interrupt  */
    uint32  slice_id;             /**<[GG]0:slice0, 1:slice1, 2: slice0+slice1 */
    uint32  core_id;              /**[AT] from at, repersent core id */
};
typedef struct sys_intr_type_s sys_intr_type_t;

typedef int32 (* SYS_INTR_EVENT_CONFIG_FUNC)(uint8 lchip, CTC_INTERRUPT_EVENT_FUNC cb);

#define INTR_TYPE_CHECK(intr) \
    do { \
        if (((intr) >= SYS_INTR_MAX) )\
        { \
            return CTC_E_INVALID_PARAM; \
        } \
    } while (0)

#define INTR_SUB_TYPE_CHECK(intr, max) \
    do { \
        if ((intr) >= (max)) \
        { \
            return CTC_E_INVALID_PARAM; \
        } \
    } while (0)

#define INTR_SUP_FUNC_TYPE_CHECK(intr) \
    do { \
        if ((intr) < SYS_INTR_PCS_LINK_31_0 || (intr) > SYS_INTR_DMA) \
        { \
            return CTC_E_INVALID_PARAM; \
        } \
    } while (0)

#define SYS_INTETRUPT_DBG_OUT(level, FMT, ...) \
    do { \
        CTC_DEBUG_OUT(interrupt, interrupt, INTERRUPT_SYS, level, FMT, ##__VA_ARGS__); \
    } while (0)

#define INTR_INDEX_VAL_SET      0
#define INTR_INDEX_VAL_RESET    1
#define INTR_INDEX_MASK_SET     2
#define INTR_INDEX_MASK_RESET   3
#define INTR_INDEX_MAX          4

/**
 @brief [GB] Define parameters of a sup-level interrupt
*/
struct sys_intr_mapping_s
{
    int32               group;                      /**< group ID of this interrupt */
    uint32              intr;                       /**< type/ID of this interrupt, refer to ctc_interrupt_type_CHIP_t */
    char                desc[CTC_INTR_DESC_LEN];    /**< description of this interrupt */
    CTC_INTERRUPT_FUNC  isr;                        /**< callback function of this interrupt */
};
typedef struct sys_intr_mapping_s sys_intr_mapping_t;

/**
 @brief [GB] Define global configure parameters to initialize interrupt module
*/
struct sys_intr_global_cfg_s
{
    uint32              group_count;                /**< count of groups */
    ctc_intr_group_t    group[SYS_USW_MAX_INTR_GROUP];  /**< array of groups */
    sys_intr_mapping_t intr[SYS_INTR_MAX];    /**< array of interrupts */
    uint8                intr_mode;                  /**< interrupt mode, 0: interrupt pin, 1: msi, 2:legacy*/
    uint8                rsv[3];
};
typedef struct sys_intr_global_cfg_s sys_intr_global_cfg_t;

struct sys_intr_func_intr_info_s
{
    uint32 tbl_id;
    uint32 sub_tbl_id;           /* 0 means useless*/
    uint8  common_type;          /* refer to sys_interrupt_type_t*/
    uint8  bit_offset;
    uint8  tbl_size;             /* indicate interrupt table have word num*/
};
typedef struct sys_intr_func_intr_info_s sys_intr_func_intr_info_t;

struct sys_intr_flexe_status_s
{
    uint8 flexe_ins;          /*Only used for flexe shim normal interrupt*/
    uint8 dir;                /*Only used for flexe shim normal interrupt, rx-0, tx-1*/
    uint8 dp;
    uint8 rsv;
    uint32* p_status;
    uint32 evt_bmp;
};
typedef struct sys_intr_flexe_status_s sys_intr_flexe_status_t;
typedef void (*sys_usw_intr_dispatch_abnormal_cb)(uint8 lchip, uint32* p_status);

struct sys_usw_intr_isr_data_s
{
    uint32 status[CTC_INTR_STAT_SIZE];
    uint8  ins; /*instance id*/
};
typedef struct sys_usw_intr_isr_data_s sys_usw_intr_isr_data_t;

#define SYS_AT_INTR_MAX_PER_CORE 112
/***************************************************************
 *
 *  Functions
 *
 ***************************************************************/
/**
 @brief Initialize interrupt module
*/
extern int32
sys_usw_interrupt_init(uint8 lchip, void* intr_global_cfg);
/**
 @brief De-Initialize interrupt module
*/
extern int32
sys_usw_interrupt_deinit(uint8 lchip);

/**
 @brief Get interrupt status
*/
extern int32
sys_usw_interrupt_get_status(uint8 lchip, sys_intr_type_t* p_type, uint32* p_status);
/**
 @brief Set interrupt enable
*/
extern int32
sys_usw_interrupt_set_en(uint8 lchip, sys_intr_type_t* p_type, uint32 enable);

/**
 @brief Get interrupt enable
*/
extern int32
sys_usw_interrupt_get_en(uint8 lchip, sys_intr_type_t* p_type, uint32* p_enable);

/**
 @brief register interrupt isr
*/
extern int32
sys_usw_interrupt_register_isr(uint8 lchip, sys_interrupt_type_t type, CTC_INTERRUPT_FUNC cb);

/**
 @brief Enable interrupt
*/
extern int32
sys_usw_interrupt_set_group_en(uint8 lchip, uint8 enable);

/**
 @brief Register event callback function
*/
extern int32
sys_usw_interrupt_register_event_cb(uint8 lchip, ctc_interrupt_event_t event, CTC_INTERRUPT_EVENT_FUNC cb);

/**
 @brief Get event callback function
*/
extern int32
sys_usw_interrupt_get_event_cb(uint8 lchip, ctc_interrupt_event_t event, CTC_INTERRUPT_EVENT_FUNC* p_cb);

/**
 @brief get event callback function
*/
extern int32
sys_usw_interrupt_get_flexe_event_cb(uint8 lchip, ctc_flexe_event_type_t flexe_event, CTC_INTERRUPT_EVENT_FUNC* p_cb);

extern int32
sys_usw_interrupt_get_info(uint8 lchip, sys_intr_type_t* p_ctc_type, uint32 intr_bit, tbls_id_t* p_intr_tbl, uint8* p_action_type, uint8* p_ecc_or_parity);
/**
 @brief Enable drv_ecc callback function
*/
extern int32
sys_usw_interrupt_proc_ecc_or_parity(uint8 lchip, tbls_id_t intr_tbl, uint32 intr_bit, ctc_intr_type_t intr_type);
/**
 @brief Get group interrupt enable or not function
*/
extern int32
sys_usw_interrupt_get_group_en(uint8 lchip, uint8* enable);


#if ((SDK_WORK_PLATFORM == 1) || ((0 == SDK_WORK_PLATFORM) && (1 == SDK_WORK_ENV)))  /* simulation */
int32
_sys_usw_interrupt_model_sim_value(uint8 lchip, uint32 tbl_id, uint32 intr, uint32* bmp, uint32 enable);
#endif

extern int32
sys_usw_interrupt_init_done(uint8 lchip);
extern int32
sys_usw_interrupt_register_flexe_isr(uint8 lchip, sys_interrupt_flexe_sub_type_t type, CTC_INTERRUPT_FUNC cb);

extern int32
sys_usw_interrupt_type_mapping(uint8 lchip, ctc_intr_type_t* p_type, sys_intr_type_t* p_sys_intr, uint8* p_count);

extern int32
_sys_usw_interrupt_get_status_normal(uint8 lchip, sys_intr_type_t* p_type, uint32* p_bmp);

extern int32
_sys_usw_interrupt_get_status_fatal(uint8 lchip, sys_intr_type_t* p_type, uint32* p_bmp);
extern int32
_sys_usw_interrupt_clear_status_normal(uint8 lchip, sys_intr_type_t* p_type, uint32* p_bmp);
extern int32
_sys_usw_interrupt_clear_status_fatal(uint8 lchip, sys_intr_type_t* p_type, uint32* p_bmp);

#ifdef __cplusplus
}
#endif

#endif

